package iharbor2

import (
	"bytes"
	"context"
	"fmt"
	"github.com/pkg/errors"
	"github.com/rclone/rclone/backend/iharbor2/api"
	"github.com/rclone/rclone/fs"
	"net/http"
	"net/url"
	"strconv"
)

///////////////////////////////
// v2 接口 上传分片文件 但无并发操作

func (f *Fs) v2RequestHttp(ctx context.Context, o *Object, body []byte, reset, MD5 string, part, off, lengsize int64) (err error) {

	fs.Debugf(o, "Upload : sending chunk %d length %d", part, len(body))
	bucket, bucketPath := o.split()
	Path := "/api/" + f.opt.Version + "/obj/" + bucket + "/" + bucketPath
	MD5 = f.ReaderMd5(ctx, bytes.NewReader(body))
	//fmt.Println("第 ", part, " 块， md5值 ", MD5, " size ", len(body))

	ExtraHeaders := map[string]string{
		//"Authorization": "Token " + f.info.Token,
		"Content-Type": "",
		"Content-MD5":  MD5,
	}
	//if err != nil {
	//	return fmt.Errorf("failed to make multipart upload for %d length file: %w", part, err)
	//}
	opts := f.HandlerAccesskeyHeader("POST", Path, 3600, url.Values{"reset": {reset}, "offset": {strconv.FormatInt(off, 10)}},
		&lengsize, ExtraHeaders, bytes.NewReader(body))

	//if MD5 == md5String {
	//	fmt.Println("块相同。。。。。。")
	//	opts.Body = in2
	//} else {
	//	fmt.Println("块不相同", part, "正确值 ", MD5, " 错误值 ", md5String)
	//
	//	return errors.New("块读取错误")
	//}

	//opts := rest.Opts{
	//	Method:     "POST",
	//	RootURL:    f.opt.Endpoint + "/api/" + f.opt.Version + "/obj/",
	//	Path:       bucket + "/" + bucketPath,
	//	Body:       body,
	//	Parameters: url.Values{"reset": {reset}, "offset": {strconv.FormatInt(off, 10)}},
	//	ExtraHeaders: map[string]string{
	//		//"Authorization": "Token " + f.info.Token,
	//		"Content-Type": "",
	//		"Content-MD5":  MD5,
	//	},
	//	ContentLength: &lengsize,
	//}
	//  http://159.226.235.47/api/v2/obj/test-bucket-s3/www/CentOS-7-x86_64-Minimal-2009.iso?offset=1006632960&reset=false
	//uploadEndpoint := f.opt.Endpoint + "/api/" + f.opt.Version + "/obj/" + bucket + "/" + bucketPath + "?offset=" + strconv.FormatInt(off, 10) + "&reset=" + reset
	var response api.UploadPartResponse
	var resp *http.Response

	count := 9 //重传次数

	err = o.fs.pacer.Call(func() (bool, error) {
		resp, err = f.srv.CallJSON(ctx, &opts, nil, &response)
		retry, err := f.shouldRetry(ctx, resp, err)
		//fmt.Println("第 ", part, "块, retry  ", retry)
		if err != nil {
			fs.Debugf(o, "Upload Error: sending chunk %d: %#v", part, err)
		}
		if retry {
			//fs.Debugf(o, "需要重新上传 %d 块 ", part, err)
		}
		return false, err
	})
	// resp 为 空 表示 没有发送数据 服务端没有正确接收，但客户端没有报错
	if err != nil || resp == nil {
		for i := 1; i <= count; i++ {
			err = f.v2RequestHttp2(ctx, o, body, reset, "", part, off, lengsize, i)
			if err == nil {
				return nil
			} else {
				fmt.Println(strconv.FormatInt(part, 10) + "第" + strconv.Itoa(i) + "次上传失败。")
			}
		}
		// 块第 count 上传失败 记录（断点续传的位置）
		err = errors.New(o.Name + "上传失败, err: " + err.Error())
	} else {
		//fmt.Println("上传第", part, "块", response.ChunkOffset, response.Chunk, response.Size, response.Created)
		fs.Debugf(o, "Upload Success: Done sending chunk %d", part)
	}
	return err
}

// 重传
func (f *Fs) v2RequestHttp2(ctx context.Context, o *Object, body []byte, reset, MD5 string, part, off, lengsize int64, count int) error {
	//fs.Debugf(o, "重新上传第 %d 块。", part)
	fs.Debugf(o, "Retransmission (%d) : send chunk %d length %d ", count, part, len(body))

	bucket, bucketPath := o.split()
	Path := "/api/" + f.opt.Version + "/obj/" + bucket + "/" + bucketPath
	MD5 = f.ReaderMd5(ctx, bytes.NewReader(body))
	ExtraHeaders := map[string]string{
		//"Authorization": "Token " + f.info.Token,
		"Content-Type": "",
		"Content-MD5":  MD5,
	}

	opts := f.HandlerAccesskeyHeader("POST", Path, 3600, url.Values{"reset": {reset}, "offset": {strconv.FormatInt(off, 10)}},
		&lengsize, ExtraHeaders, bytes.NewReader(body))
	//opts := rest.Opts{
	//	Method:     "POST",
	//	RootURL:    f.opt.Endpoint + "/api/" + f.opt.Version + "/obj/",
	//	Path:       bucket + "/" + bucketPath,
	//	Body:       body,
	//	Parameters: url.Values{"reset": {reset}, "offset": {strconv.FormatInt(off, 10)}},
	//	ExtraHeaders: map[string]string{
	//		//"Authorization": "Token " + f.info.Token,
	//		"Content-Type": "",
	//		"Content-MD5":  MD5,
	//	},
	//	ContentLength: &lengsize,
	//}

	var response api.UploadPartResponse

	err := o.fs.pacer.CallNoRetry(func() (bool, error) {
		resp, err := f.srv.CallJSON(ctx, &opts, nil, &response)
		retry, err := f.shouldRetry(ctx, resp, err)
		if err != nil {
			fs.Debugf(o, "Retransmission (%d) Error: resend chunk %d : %+v", count, part, err.Error())
		}
		if retry {
			//fmt.Printf("第 %d 块重传失败 \n", part)
		}
		if resp == nil {
			//fmt.Println("重传第 ", part, "块, 响应 ", response.Created)
			return false, errors.New("块" + strconv.FormatInt(part, 10) + " - 第" + strconv.Itoa(count) + "重传失败")
		}
		return false, err
	})
	if err == nil {
		fs.Debugf(o, "Retransmission (%d) Success : Done resend chunk %d", count, part)
	}
	return err
}
